<?php

namespace yifang\log;

use yifang\lib\Event;
use yifang\log\contract\LogHandlerInterface;
use yifang\event\LogRecord;
use yifang\event\LogWrite;

class Channel
{
    protected $name;
    protected $logger;
    protected $event;

    protected $lazy = true;

    /**
     * 日志信息
     * @var array
     */
    protected $log = [];

    /**
     * 关闭日志
     * @var array
     */
    protected $close = false;

    /**
     * 允许写入类型
     * @var array
     */
    protected $allow = [];

    public function __construct($name, LogHandlerInterface $logger, array $allow, $lazy = true, Event $event = null)
    {
        $this->name   = $name;
        $this->logger = $logger;
        $this->allow  = $allow;
        $this->lazy   = $lazy;
        $this->event  = $event;
    }

    /**
     * 关闭通道
     */
    public function close()
    {
        $this->clear();
        $this->close = true;
    }

    /**
     * 清空日志
     */
    public function clear()
    {
        $this->log = [];
    }

    /**
     * 记录日志信息
     */
    public function record($msg, $type = 'info', array $context = [], $lazy = true)
    {
        if ($this->close || (!empty($this->allow) && !in_array($type, $this->allow))) {
            return $this;
        }
        if (is_string($msg) && !empty($context)) {
            $replace = [];
            foreach ($context as $key => $val) {
                $replace['{' . $key . '}'] = $val;
            }
            $msg = strtr($msg, $replace);
        }
        if (!empty($msg) || 0 === $msg) {
            $this->log[$type][] = $msg;
            if ($this->event) {
                $this->event->trigger(new LogRecord($type, $msg));
            }
        }
        if (!$this->lazy || !$lazy) {
            $this->save();
        }
        return $this;
    }

    /**
     * 实时写入日志信息
     */
    public function write($msg, $type = 'info', array $context = [])
    {
        return $this->record($msg, $type, $context, false);
    }

    /**
     * 获取日志信息
     * @return array
     */
    public function getLog()
    {
        return $this->log;
    }

    /**
     * 保存日志
     */
    public function save()
    {
        $log = $this->log;
        if ($this->event) {
            $event = new LogWrite($this->name, $log);
            $this->event->trigger($event);
        }
        if ($this->logger->save($log)) {
            $this->clear();
            return true;
        }
        return false;
    }

    /**
     * 系统不可用。
     */
    public function emergency($message, array $context = [])
    {
        $this->log(__FUNCTION__, $message, $context);
    }

    /**
     * alert
     */
    public function alert($message, array $context = [])
    {
        $this->log(__FUNCTION__, $message, $context);
    }

    /**
     * Critical conditions.
     */
    public function critical($message, array $context = [])
    {
        $this->log(__FUNCTION__, $message, $context);
    }

    /**
     * Error
     */
    public function error($message, array $context = [])
    {
        $this->log(__FUNCTION__, $message, $context);
    }

    /**
     * warning
     */
    public function warning($message, array $context = [])
    {
        $this->log(__FUNCTION__, $message, $context);
    }

    /**
     * notice
     */
    public function notice($message, array $context = [])
    {
        $this->log(__FUNCTION__, $message, $context);
    }

    /**
     * info
     */
    public function info($message, array $context = [])
    {
        $this->log(__FUNCTION__, $message, $context);
    }

    /**
     * debug
     */
    public function debug($message, array $context = [])
    {
        $this->log(__FUNCTION__, $message, $context);
    }

    /**
     * log
     */
    public function log($level, $message, array $context = [])
    {
        $this->record($message, $level, $context);
    }

    public function __call($method, $parameters)
    {
        $this->log($method, ...$parameters);
    }
}
